#include "area_index.h"

#include <string>
#include <boost/algorithm/string.hpp>

#include "base/logging.h"
#include "base/config_reader.h"
#include "database/scoped_connection.h"
#include "database/simple_db_pool.h"

#include "robot_thread_manager.h"
#include "shop_info_cache.h"

namespace imserver {

using apache::thrift::concurrency::Runnable;

class ReloadAreaIndexTask : public Runnable  {
 public:
  ReloadAreaIndexTask(){}
  virtual void run() {
    AreaIndex::Instance().Reload();
    GetTimerManager()->add(boost::shared_ptr<Runnable>(new ReloadAreaIndexTask()), 3600 * 1000);
  }
};

AreaIndex::AreaIndex() : db_conn_pool_(NULL) {
  ConfigReader config("../conf/bang_robot_service.conf");

  db_conn_pool_ = new base::SimpleConnectionPool(config.Get("shop_db", "name").c_str(),
                      config.Get("shop_db", "server_list").c_str(),
                      config.Get("shop_db", "user").c_str(),
                      config.Get("shop_db", "password").c_str());
  GetTimerManager()->add(boost::shared_ptr<Runnable>(new ReloadAreaIndexTask()), 60 * 1000);
}

std::set<int64_t> AreaIndex::Get(const std::string & city_code, const std::string & area_code, const std::string & quan_code) const {
  boost::shared_lock<boost::shared_mutex> rlock(mutex_);

  std::map<std::string, std::set<int64_t> >::const_iterator it = area_index_.find(city_code + ':' + area_code + ':' + quan_code);
  if (it != area_index_.end() && it->second.size() > 1) {
    return it->second;
  }
  it = area_index_.find(city_code + ':' + area_code);
  if (it != area_index_.end() && it->second.size() > 1) {
    return it->second;
  }
  it = area_index_.find(city_code);
  if (it != area_index_.end() && it->second.size() > 1) {
    return it->second;
  }

  std::vector<int64_t> rand_shops;
  ShopInfoCache::Instance().RandomGetShops(5, &rand_shops);
  LOG_DEBUG("not a shop keeper, return rand shops=" << rand_shops.size());
  
  std::set<int64_t> ret(rand_shops.begin(), rand_shops.end());
  // std::copy(rand_shops.begin(), rand_shops.end(), std::back_inserter(ret, ret.end()));
  return ret;
}

int AreaIndex::Reload() {
  mysqlpp::ScopedConnection db(*db_conn_pool_);
  if (!db) {
    LOG_ERROR("Failed to get a connection from database-pool.");
    return -1;
  }

  std::map<std::string, std::set<int64_t> > area_index;

  mysqlpp::Query query(db->query());
  query << "SELECT qid, addr_city_code, addr_area_code, addr_areaquan_code FROM shop_base";

  try {
    mysqlpp::UseQueryResult ret = query.use();
    if (ret) {
      while(mysqlpp::Row row = ret.fetch_row()) {
        int64_t qid = row["qid"];
      //shops[qid].qid = qid;
        std::string city = row["addr_city_code"].c_str();
        std::string area = row["addr_area_code"].c_str();
        std::string quan = row["addr_areaquan_code"].c_str();
        boost::trim(city);
        boost::trim(area);
        boost::trim(quan);
	if (!city.empty()) {
          area_index[city].insert(qid);
          LOG_INFO("load area_index " << qid << " " << city);
	  if (!area.empty()) {
            area_index[city + ':' + area].insert(qid);
            LOG_INFO("load area_index " << qid << " " << city << ':' << area);
	    if (!quan.empty()) {
              area_index[city + ':' + area + ':' + quan].insert(qid);
            LOG_INFO("load area_index " << qid << " " << city << ':' << area << ':' << quan);
            }
          } 
        }
        LOG_INFO("load area_index " << qid << " city=" << city << " area=" << area << " quan=" << quan);
      }
    }
  } catch (mysqlpp::Exception& e) {
    LOG_ERROR(query.str() << " EXEC ERROR.(" << e.what() << ")");
    return -2;
  }

  area_index["bei_jing"].insert(127646892);
  area_index["bei_jing:33"].insert(127646892);

  LOG_INFO("Reload area_index ok, size=" << area_index.size());
  {
    boost::unique_lock<boost::shared_mutex> wlock(mutex_);
    area_index_.swap(area_index);
  }
  return 0;
}

}

